package nus.mtech.subscription;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import nus.mtech.subscription.ExtraFeature.ExtraFeatureType;

/**
 * 
 */

/**
 * @author Chew Xunmao
 * 
 */
public class SubscriptionManager {
	private static SubscriptionManager SubscriptionManagerInstance;
	private HashMap<String, ArrayList<Subscription>> mapOfSubscriptions = new HashMap<String, ArrayList<Subscription>>();

	public HashMap<String, ArrayList<Subscription>> getMapOfSubscriptions() {
		return mapOfSubscriptions;

	}

	public void setMapOfSubscriptions(
			HashMap<String, ArrayList<Subscription>> mapOfSubscriptions) {
		this.mapOfSubscriptions = mapOfSubscriptions;
	}

	public static SubscriptionManager getSubscriptionManagerInstance() {
		if (SubscriptionManagerInstance != null)
			return SubscriptionManagerInstance;
		else {
			SubscriptionManagerInstance = new SubscriptionManager();
			return SubscriptionManagerInstance;
		}
	}

	private SubscriptionManager() {

	}

	public void addSubscription(String accountNo,
			Subscription newSubscriptionObject) {
		// Assume one account can only have one subscription for each type.
		if (mapOfSubscriptions.containsKey(accountNo)) {
			ArrayList<Subscription> subses = mapOfSubscriptions.get(accountNo);
			ArrayList<Subscription> subsesToRemove = new ArrayList<Subscription>();
			for (Subscription sub : subses) {
				if (newSubscriptionObject.getClass() == sub.getClass()) {
					subsesToRemove.add(sub);
				}
			}
			subses.removeAll(subsesToRemove);
			subses.add(newSubscriptionObject);
			mapOfSubscriptions.remove(accountNo);
			mapOfSubscriptions.put(accountNo, subses);
		} else {
			ArrayList<Subscription> lNewSubscriptions = new ArrayList<Subscription>();
			lNewSubscriptions.add(newSubscriptionObject);
			mapOfSubscriptions.put(accountNo, lNewSubscriptions);
		}
	}

	// remember to check for null when using this method
	public ArrayList<Subscription> getSubscription(String accountNo) {
		if (mapOfSubscriptions.containsKey(accountNo))
			return mapOfSubscriptions.get(accountNo);
		else
			return null;
	}

	public MobileVoice createMobileVoiceSubscription(Date startDate,
			Date endDate, boolean activeStatus) {
		MobileVoice lNewMobileVoice = new MobileVoice(startDate, endDate,
				activeStatus);
		return lNewMobileVoice;
	}

	public DigitalVoice createDigitalVoiceSubscription(long telno,
			Date startDate, Date endDate, boolean activeStatus) {

		DigitalVoice lNewDigitialVoice = new DigitalVoice(telno, startDate,
				endDate);
		return lNewDigitialVoice;
	}

	public CableTV createCableTVSubscription(Date startDate, Date endDate,
			boolean activeStatus) {

		CableTV lNewCableTV = new CableTV(startDate, endDate, activeStatus);
		return lNewCableTV;
	}

	public void addExtraFeature(ExtraFeatureType type, Date startDate,
			Date endDate, boolean activeStatus, Subscription lSubObject) {

		ExtraFeature lNewFeature = new ExtraFeature(type, startDate, endDate);

		if (lSubObject instanceof MobileVoice) {
			MobileVoice lTempMobileVoiceObj = (MobileVoice) lSubObject;

			if (lTempMobileVoiceObj.getMapOfExtraFeatures().containsKey(type)) {
				lTempMobileVoiceObj.getMapOfExtraFeatures().remove(type);
			} else
				lTempMobileVoiceObj.getMapOfExtraFeatures().put(type,
						lNewFeature);
		}

		if (lSubObject instanceof DigitalVoice) {
			DigitalVoice lTempDigitialVoice = (DigitalVoice) lSubObject;
			lTempDigitialVoice
					.setExtraFeature(startDate, endDate, activeStatus);
		}

	}

	public void addExtraCableTVChannels(String lCableTVName, Date startDate,
			Date endDate, CableTV cableTVObj) {

		CableTVChannel lNewCableTvChannel = new CableTVChannel(
				ExtraFeatureType.OptionalChannel, lCableTVName, startDate,
				endDate);
		cableTVObj.addChannel(lCableTVName, lNewCableTvChannel);

	}

	public ExtraFeature getExtraFeaturesFromSubscription(ExtraFeatureType type,
			Subscription subObj) {
		ExtraFeature lRetExtFeature = null;
		if (subObj instanceof MobileVoice) {
			MobileVoice lTmpObj = (MobileVoice) subObj;
			if (lTmpObj.getMapOfExtraFeatures().containsKey(type)) {
				lRetExtFeature = lTmpObj.getMapOfExtraFeatures().get(type);
			}
		}
		if (subObj instanceof DigitalVoice) {
			DigitalVoice lTmpObj = (DigitalVoice) subObj;
			lRetExtFeature = lTmpObj.getExtraFeature();
		}
		return lRetExtFeature;
	}

	public ArrayList<CableTVChannel> getExtraCableTVChannels(
			ExtraFeatureType type, CableTV cableObj) {
		return cableObj.getChannels();

	}

	public boolean removeCableTVChannel(CableTV cableTvObj, String channelName) {
		if (cableTvObj.getChannels().contains(channelName)) {
			cableTvObj.getChannels().remove(channelName);
			return true;
		} else
			return false;
	}

	public boolean updateSubscription(String accountNo, Subscription subObj) {
		ArrayList<Subscription> lListOfSubObj = getSubscription(accountNo);
		boolean lReturnUpdate = false;
		for (Subscription lTmpObj : lListOfSubObj) {
			if (lTmpObj instanceof MobileVoice && subObj instanceof MobileVoice) {
				lListOfSubObj.remove(lTmpObj);
				lReturnUpdate = true;
				break;
			}

			if (lTmpObj instanceof DigitalVoice
					&& subObj instanceof DigitalVoice) {
				lListOfSubObj.remove(lTmpObj);
				lReturnUpdate = true;
				break;
			}

			if (lTmpObj instanceof CableTV && subObj instanceof CableTV) {
				lListOfSubObj.remove(lTmpObj);
				lReturnUpdate = true;
				break;
			}

		}
		if (lReturnUpdate)
			lListOfSubObj.add(subObj);
		return lReturnUpdate;
	}

	public boolean updateCableTVChannel(CableTV cableTVObj,
			CableTVChannel channelObject) {
		// cableTVObj.getChannels()
		boolean lReturnResult = false;
		if (null != cableTVObj.getChannels()) {
			for (CableTVChannel lTmpCableTVChannel : cableTVObj.getChannels()) {
				if (lTmpCableTVChannel.getChannelName().equalsIgnoreCase(
						channelObject.getChannelName())) {
					cableTVObj.getChannels().remove(lTmpCableTVChannel);
					lReturnResult = true;
					break;
				}
			}
		}
		if (lReturnResult)
			cableTVObj
					.addChannel(channelObject.getChannelName(), channelObject);

		return lReturnResult;

	}

	public void setNull() {
		SubscriptionManagerInstance = null;
	}

}
